home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Utilities / uupc 3.1 / (uupc π) / dcpfpkt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-01  |  6.3 KB  |  320 lines  |  [TEXT/KAHL]

  1. /* $Header: fio.c,v 1.20 85/04/30 12:57:32 rick Exp $ */
  2. /*    %M%    %I%    %E%    (Mathematisch Centrum)    */
  3.  
  4. /*
  5.  * flow control protocol.
  6.  *
  7.  * This protocol relies on flow control of the data stream.
  8.  * It is meant for working over links that can (almost) be
  9.  * guaranteed to be errorfree, specifically X.25/PAD links.
  10.  * A sumcheck is carried out over a whole file only. If a
  11.  * transport fails the receiver can request retransmission(s).
  12.  * This protocol uses a 7-bit datapath only, so it can be
  13.  * used on links that are not 8-bit transparent.
  14.  *
  15.  * When using this protocol with an X.25 PAD:
  16.  * Although this protocol uses no control chars except CR,
  17.  * control chars NULL and ^P are used before this protocol
  18.  * is started; since ^P is the default char for accessing
  19.  * PAD X.28 command mode, be sure to disable that access
  20.  * (PAD par 1). Also make sure both flow control pars
  21.  * (5 and 12) are set. The CR used in this proto is meant
  22.  * to trigger packet transmission, hence par 3 should be 
  23.  * set to 2; a good value for the Idle Timer (par 4) is 10.
  24.  * All other pars should be set to 0.
  25.  * Normally a calling site will take care of setting the
  26.  * local PAD pars via an X.28 command and those of the remote
  27.  * PAD via an X.29 command, unless the remote site has a
  28.  * special channel assigned for this protocol with the proper
  29.  * par settings.
  30.  *
  31.  * Author: Piet Beertema, CWI, Amsterdam, Sep 1984
  32.  * Adapted to uupc 3.0 and THINK C 4.0 by Dave Platt, Jul 1991
  33.  */
  34.  
  35. /*
  36.             Portions Copyright © David Platt, 1992, 1991.  All Rights Reserved
  37.             Worldwide.
  38. */
  39.  
  40. #include "dcp.h"
  41.  
  42. #define PKTSIZE   128
  43.  
  44. #ifndef MAXMSGLEN
  45. #define MAXMSGLEN    BUFSIZ
  46. #endif MAXMSGLEN
  47.  
  48. #include "dcpfpkt.proto.h"
  49.  
  50. static int chksum;
  51.  
  52. int fopenpk(int master)
  53. {
  54.     flowcontrol(TRUE, useHardwareFlowControl);
  55.     pktsize = PKTSIZE;
  56.     msgtime = MSGTIME;
  57.     zzz(2); /* Give peer time to perform corresponding port setup */
  58.     return OK;
  59. }
  60.  
  61. fclosepk(void)
  62. {
  63.     flowcontrol(FALSE, FALSE);
  64.     return OK;
  65. }
  66.  
  67. fwrmsg(char *str, boolean nowait)
  68. {
  69.     register char *s;
  70.     char bufr[MAXMSGLEN];
  71.  
  72.     s = bufr;
  73.     while (*str)
  74.         *s++ = *str++;
  75.     if (*(s-1) == '\n')
  76.         s--;
  77.     *s++ = '\r';
  78.     (void) swrite(bufr, s - bufr);
  79.     return OK;
  80. }
  81.  
  82. frdmsg(register char *str, int *bytes)
  83. {
  84.     register char *smax;
  85.     char *base = str;
  86.  
  87.     smax = str + MAXPACK - 1;
  88.     for (;;) {
  89.         if (sread(str, 1, msgtime) <= 0)
  90.             goto msgerr;
  91.         if (*str == '\r')
  92.             break;
  93.         if (*str < ' ')
  94.             continue;
  95.         if (str++ >= smax)
  96.             goto msgerr;
  97.     }
  98.     *str = '\0';
  99.     *bytes = strlen(base) + 1;
  100.     return OK;
  101. msgerr:
  102.     return FAILED;
  103. }
  104.  
  105.  
  106. fgetpkt(char *packet, int *bytes)
  107. {
  108.     register char *op, c, *ip;
  109.     register int sum, len, nl, left;
  110.     char buf[5], tbuf[MAXPACK];
  111.     int i, tleft, sready, slept;
  112.     static char special = 0;
  113.     
  114.     left = pktsize;
  115.     op = packet;
  116.     sum = chksum;
  117.     tleft = 0;
  118.  
  119.     do {
  120.         if (tleft == 0) {
  121.             ip = tbuf;
  122.             sready = savail();
  123.             if (sready > MAXPACK) {
  124.                 sready = MAXPACK;
  125.             }
  126.             if (sready > left) {
  127.                 sready = left;
  128.             } else if (sready == 0) {
  129.                 sready = 1;
  130.             }
  131.             len = sread(ip, sready, msgtime);
  132.             if (len == 0) {
  133.                 printmsg(0, "Timeout occurred while reading data");
  134.                 return FAILED; /* fail if timed out */
  135.             }
  136.             tleft = len;
  137.         }
  138.         if ((*ip &= 0177) >= '\172') {
  139.             if (special) {
  140.                 special = 0;
  141.                 if (*ip++ != '\176') {
  142.                     printmsg(0, "End-of-file checksum sequence garbled");
  143.                     goto dcorr;
  144.                 }
  145.                 tleft--;
  146.                 if (tleft > 0) {
  147.                     if (tleft > 5) tleft = 5;
  148.                     memcpy(buf, ip, tleft);
  149.                     len = tleft;
  150.                 } else {
  151.                     len = 0;
  152.                 }
  153.                 while (len < 5) {
  154.                     i = sread(&buf[len], 5 - len, msgtime);
  155.                     if (i == 0) {
  156.                         len = FAILED;
  157.                         printmsg(0, "Timeout occurred while reading checksum");
  158.                         goto dcorr;
  159.                     }
  160.                     len += i;
  161.                 }
  162.                 if (buf[4] != '\r')
  163.                     goto dcorr;
  164.                 sscanf(buf, "%4x", &chksum);
  165.                 if (chksum == sum) {
  166.                     *bytes = packet - op; /* return negative count to signal EOF */
  167.                     remote_stats.breceived -= *bytes;
  168.                     return OK;
  169.                 } else {
  170.                     printmsg(0, "Checksum mismatch, told %04x, calc %04x", chksum, sum);
  171.                     *bytes = op - packet;
  172.                     remote_stats.breceived -= *bytes;
  173.                     fsendresp(RETRY);
  174.                     return 'R';
  175.                 }
  176.             }
  177.             special = *ip++;
  178.         } else {
  179.             if (*ip < '\040') {
  180.                 /* error: shouldn't get control chars */
  181.                 printmsg(0, "Received a control character (shouldn't have!)");
  182.                 goto dcorr;
  183.             }
  184.             switch (special) {
  185.             case 0:
  186.                 c = *ip++;
  187.                 break;
  188.             case '\172':
  189.                 c = *ip++ - 0100;
  190.                 break;
  191.             case '\173':
  192.                 c = *ip++ + 0100;
  193.                 break;
  194.             case '\174':
  195.                 c = *ip++ + 0100;
  196.                 break;
  197.             case '\175':
  198.                 c = *ip++ + 0200;
  199.                 break;
  200.             case '\176':
  201.                 c = *ip++ + 0300;
  202.                 break;
  203.             }
  204.             *op++ = c;
  205.             left --;
  206.             if (sum & 0x8000) {
  207.                 sum <<= 1;
  208.                 sum++;
  209.             } else
  210.                 sum <<= 1;
  211.             sum += c & 0377;
  212.             sum &= 0xffff;
  213.             special = 0;
  214.         }
  215.         tleft--;
  216.     } while (left > 0);
  217.     *bytes = pktsize;
  218.     chksum = sum;
  219.     remote_stats.breceived += pktsize;
  220.     return OK;
  221. dcorr:
  222.     printmsg (0, "Data corrupted, skipping to EOF");
  223.     while (sread(tbuf, 1, msgtime) > 0) {
  224.         /* spin really fast */
  225.     }
  226.     fsendresp(RETRY);
  227.     return 'R';
  228. }
  229.  
  230. fsendpkt(char *ip, int len, int flag)
  231. {
  232.     register char *op;
  233.     register int sum, nl;
  234.     int ret;
  235.     char obuf[MAXPACK * 2];
  236.     op = obuf;
  237.     nl = 0;
  238.     sum = chksum;
  239.     if (flag) {
  240.         len = strlen(ip)+1;
  241.     } else {
  242.         if (len == 0) return;
  243.     }
  244.     remote_stats.bsent += len;
  245.     do {
  246.         if (sum & 0x8000) {
  247.             sum <<= 1;
  248.             sum++;
  249.         } else
  250.             sum <<= 1;
  251.         sum += *ip & 0377;
  252.         sum &= 0xffff;
  253.         if (*ip & 0200) {
  254.             *ip &= 0177;
  255.             if (*ip < 040) {
  256.                 *op++ = '\174';
  257.                 *op++ = *ip++ + 0100;
  258.             } else
  259.             if (*ip <= 0171) {
  260.                 *op++ = '\175';
  261.                 *op++ = *ip++;
  262.             }
  263.             else {
  264.                 *op++ = '\176';
  265.                 *op++ = *ip++ - 0100;
  266.             }
  267.             nl += 2;
  268.         } else {
  269.             if (*ip < 040) {
  270.                 *op++ = '\172';
  271.                 *op++ = *ip++ + 0100;
  272.                 nl += 2;
  273.             } else
  274.             if (*ip <= 0171) {
  275.                 *op++ = *ip++;
  276.                 nl++;
  277.             } else {
  278.                 *op++ = '\173';
  279.                 *op++ = *ip++ - 0100;
  280.                 nl += 2;
  281.             }
  282.         }
  283.     } while (--len > 0);
  284.     chksum = sum;
  285.     ret = swrite(obuf, nl);
  286.     return ret == nl ? nl : ret < 0 ? 0 : -ret;
  287. }
  288.  
  289. int ffilepkt(void)
  290. {
  291.     chksum = 0xffff;
  292.     return 0;
  293. }
  294.  
  295. feofpkt(void)
  296. {
  297.     char ibuf[MAXMSGLEN], ack;
  298.     int len;
  299.     sprintf(ibuf, "\176\176%04x", chksum);
  300.     fwrmsg(ibuf, FALSE);
  301.     ack = 'A';
  302.     if (frdmsg(ibuf, &len) != FAILED) {
  303.         ack = ibuf[0];
  304.     }
  305.     return ack;
  306. }
  307.  
  308. int fsendresp(int state)
  309. {
  310.     char spacket[64];
  311.     switch (state) {
  312.      case OK:
  313.         return (fwrmsg("G", FALSE));
  314.      case RETRY:
  315.         return (fwrmsg("R", FALSE));
  316.      default:
  317.         return (fwrmsg("Q", FALSE));
  318.     }
  319. }
  320.